using ChatBackend.Models;
using SqlSugar;

namespace ChatBackend.Repositories
{
    public class ChatRoomRepository : IChatRoomRepository
    {
        private readonly ISqlSugarClient _db;

        public ChatRoomRepository(ISqlSugarClient db)
        {
            _db = db;
        }

        public async Task<ChatRoom?> GetByIdAsync(int id)
        {
            try
            {
                var list = await _db.Queryable<ChatRoom>()
                    .Where(cr => cr.Id == id && cr.IsActive)
                    .ToListAsync();
                return list.FirstOrDefault();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"GetByIdAsync error: {ex.Message}");
                return null;
            }
        }

        public async Task<List<ChatRoom>> GetUserChatRoomsAsync(int userId)
        {
            return await _db.Queryable<ChatRoom>()
                .LeftJoin<UserChatRoom>((cr, ucr) => cr.Id == ucr.ChatRoomId)
                .Where((cr, ucr) => ucr.UserId == userId && ucr.IsActive && cr.IsActive)
                .Select(cr => cr)
                .ToListAsync();
        }

        public async Task<ChatRoom?> GetDirectChatRoomAsync(int user1Id, int user2Id)
        {
            var chatRoomIds = await _db.Queryable<UserChatRoom>()
                .Where(ucr => ucr.UserId == user1Id && ucr.IsActive)
                .Select(ucr => ucr.ChatRoomId)
                .ToListAsync();

            if (!chatRoomIds.Any()) return null;

            var commonChatRoomId = await _db.Queryable<UserChatRoom>()
                .Where(ucr => ucr.UserId == user2Id && ucr.IsActive && chatRoomIds.Contains(ucr.ChatRoomId))
                .Select(ucr => ucr.ChatRoomId)
                .FirstAsync();

            if (commonChatRoomId == 0) return null;

            return await _db.Queryable<ChatRoom>()
                .Where(cr => cr.Id == commonChatRoomId && cr.Type == ChatRoomType.Direct && cr.IsActive)
                .FirstAsync();
        }

        public async Task<ChatRoom> CreateAsync(ChatRoom chatRoom)
        {
            chatRoom.CreatedAt = DateTime.UtcNow;
            chatRoom.UpdatedAt = DateTime.UtcNow;
            
            var result = await _db.Insertable(chatRoom).ExecuteReturnEntityAsync();
            return result;
        }

        public async Task<ChatRoom> UpdateAsync(ChatRoom chatRoom)
        {
            chatRoom.UpdatedAt = DateTime.UtcNow;
            await _db.Updateable(chatRoom).ExecuteCommandAsync();
            return chatRoom;
        }

        public async Task<bool> DeleteAsync(int id)
        {
            var result = await _db.Updateable<ChatRoom>()
                .SetColumns(cr => new ChatRoom { IsActive = false, UpdatedAt = DateTime.UtcNow })
                .Where(cr => cr.Id == id)
                .ExecuteCommandAsync();
            return result > 0;
        }

        public async Task<bool> ExistsAsync(int id)
        {
            return await _db.Queryable<ChatRoom>()
                .Where(cr => cr.Id == id && cr.IsActive)
                .AnyAsync();
        }

        public async Task<bool> IsUserMemberAsync(int chatRoomId, int userId)
        {
            return await _db.Queryable<UserChatRoom>()
                .Where(ucr => ucr.ChatRoomId == chatRoomId && ucr.UserId == userId && ucr.IsActive)
                .AnyAsync();
        }

        public async Task AddUserToChatRoomAsync(int chatRoomId, int userId, UserRole role = UserRole.Member)
        {
            var userChatRoom = new UserChatRoom
            {
                ChatRoomId = chatRoomId,
                UserId = userId,
                Role = role,
                JoinedAt = DateTime.UtcNow,
                IsActive = true
            };

            await _db.Insertable(userChatRoom).ExecuteCommandAsync();
        }

        public async Task RemoveUserFromChatRoomAsync(int chatRoomId, int userId)
        {
            await _db.Updateable<UserChatRoom>()
                .SetColumns(ucr => new UserChatRoom { IsActive = false })
                .Where(ucr => ucr.ChatRoomId == chatRoomId && ucr.UserId == userId)
                .ExecuteCommandAsync();
        }

        public async Task<List<User>> GetChatRoomMembersAsync(int chatRoomId)
        {
            return await _db.Queryable<User>()
                .LeftJoin<UserChatRoom>((u, ucr) => u.Id == ucr.UserId)
                .Where((u, ucr) => ucr.ChatRoomId == chatRoomId && ucr.IsActive)
                .Select(u => u)
                .ToListAsync();
        }

        public async Task<UserChatRoom?> GetUserChatRoomAsync(int chatRoomId, int userId)
        {
            try
            {
                var list = await _db.Queryable<UserChatRoom>()
                    .Where(ucr => ucr.ChatRoomId == chatRoomId && ucr.UserId == userId && ucr.IsActive)
                    .ToListAsync();
                return list.FirstOrDefault();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"GetUserChatRoomAsync error: {ex.Message}");
                return null;
            }
        }

        public async Task UpdateLastReadAsync(int chatRoomId, int userId, DateTime lastRead)
        {
            var lastReadString = lastRead.ToString("yyyy-MM-dd HH:mm:ss.fff");

            await _db.Updateable<UserChatRoom>()
                .SetColumns(ucr => new UserChatRoom { LastReadAtString = lastReadString })
                .Where(ucr => ucr.ChatRoomId == chatRoomId && ucr.UserId == userId)
                .ExecuteCommandAsync();
        }
    }
}
